#include "online_update.h"


IAP_BTLD       iap_btld;
PRPCESS_STATUS process;

uint8_t status;
uint8_t flash_write[3];

void set_flash_setting_sector( uint8_t process, float software_version )
{
  int16_t temp = 0;
  flash_write[0] = process;
  temp = software_version * 10;
  flash_write[1] = temp >> 8;
  flash_write[2] = temp;
  mcu_flash_write(SETTING_SECTOR_ADDR, flash_write, 3 );

}
void set_bootloader_copy_app3_to_app1( void )
{
  set_flash_setting_sector( Copy_APP3_To_APP1,rk.hyper_parameter.software_version );

}


void start_bootloader_recv_bin( uint8_t *data )
{
  uint16_t temp = 0;
  float temp_f = 0.0f;
  temp = (data[0] << 8) | data[1];
  temp_f = (float)temp * 0.1f;

  set_flash_setting_sector( Recv_New_APP_To_APP2, temp_f );
  rk.flag.system_restart = true;
}

typedef void (*jump_callback)(void);

uint8_t jump_app(uint32_t app_addr)
{
  uint32_t sp = *(__IO uint32_t*)app_addr;
  uint32_t reset_handler = *(__IO uint32_t*)(app_addr + 4);
  jump_callback app1;

//  uart_log("run app1 step1...\r\n");
  // 1. 检查栈指针有效性
  if ((sp & 0x2FFE0000) != 0x20000000) { // 更宽松的RAM地址检查

      return 0;

  }

  // 2. 复位外设（可选）
//  RCC->AHB1RSTR |= 0xFFFFFFFF;
//  RCC->AHB1RSTR = 0;


  // 3. 关闭所有中断
  __disable_irq();

  //4. 清除中断挂起标志
  for (int i = 0; i < 8; i++)
  {
  NVIC->ICER[i] = 0xFFFFFFFF;  // 禁用中断
  NVIC->ICPR[i] = 0xFFFFFFFF;  // 清除挂起位
  }

  // 5. 设置堆栈指针并跳转
  app1 = (jump_callback)reset_handler;
  __set_MSP(sp);

  app1();

  // 此处不会执行
  return 0;
}
void recv_bin_handle( uint8_t *data, uint16_t size )
{
  char str[56];
  uint8_t datapos   = 0;

  iap_btld.this_id      = (data[datapos] << 8) | data[datapos+1];
  datapos+=2;
  iap_btld.split_size   = (data[datapos] << 8) | data[datapos+1];
  datapos+=2;
  iap_btld.split_count  = (data[datapos] << 8) | data[datapos+1];
  datapos+=2;
  iap_btld.this_count   = (data[datapos] << 8) | data[datapos+1];
  datapos+=2;
  iap_btld.this_size    = (data[datapos] << 8) | data[datapos+1];
  datapos+=2;

  sprintf(str, "device revc : bin sub package, split count : %d, this count : %d\r\n", iap_btld.split_count, iap_btld.this_count );
  uart_log( str );
  HAL_Delay(20);
  // 校验
  if( (iap_btld.this_size == 0) && (iap_btld.this_count == iap_btld.split_count) )
  {
    rk.flag.iap_update_start = true;
    return ;
  }

  if( iap_btld.this_id != iap_btld.target_id )
  {
    iap_btld.error_type = 0x01;
  }
  else if( iap_btld.this_count - iap_btld.last_count != 1 )
  {
    iap_btld.error_type = 0x04;
  }
  else if( (iap_btld.this_size != iap_btld.split_size) || (iap_btld.this_size != 1024 ))
  {
    iap_btld.error_type = 0x05;
  }

  //校验通过后往flash写数据
  if( iap_btld.error_type == 0x00 )
  {
    memcpy( iap_btld.data, data+datapos, iap_btld.this_size );
    if( (iap_btld.this_count == 1) && (iap_btld.data[3] != 0x20) )
    {
      iap_btld.error_type = 0x02;
    }
    else
    {
      if( mcu_flash_write( ADDR_FLASH_SECTOR_6 + (iap_btld.this_count - 1) * iap_btld.this_size, iap_btld.data, iap_btld.this_size ) != Read_OK )
      {
        iap_btld.error_type = 0x03;
      }
      else
      {
        iap_btld.last_count = iap_btld.this_count;

        sprintf(str, "flash write success, this sub count : %d\r\n", iap_btld.this_count );

        uart_log( str );
      }
    }

  }

  // 错误后的当前包序
  if( iap_btld.error_type == 0x04 )
  {
    iap_btld.now_count = iap_btld.last_count + 1;
  }
  else
  {
    iap_btld.now_count = 0;
  }
  rk.upload.confirm_type = AFN_IAP_Update_Work;
  upload_package = upload_iap_package;
  upload_package_init();
  upload_package_crc_end( upload_package() );
}

void bootloader_prepare( void )
{
  char str[56];

  __enable_irq();          // 开启全局中断
  mcu_flash_read( SETTING_SECTOR_ADDR, iap_btld.flash_readdata, 3 );
  process = iap_btld.flash_readdata[0];
  if( process == 0xFF )
  {
    process = Start_APP1;
  }
  iap_btld.target_id = (iap_btld.flash_readdata[1] << 8) | iap_btld.flash_readdata[2];
  sprintf(str, "->->-> bootloader, process : %d\r\n",process );
  uart_log( str );

}

void bootloader_work( void )
{
  static uint8_t flag_first = 0;
  char str[56];
  switch (process)
  {
    case Start_APP1:
      HAL_Delay(20);
      app1_start_count_get();
      HAL_Delay(20);
      sprintf(str, "app1 start count : %d\r\n", iap_btld.app1_start_count+1 );
      uart_log( str );
      if( iap_btld.app1_start_count+1 >= 5 )
      {
        iap_btld.app1_start_count = 0;
        HAL_Delay(20);
        app1_start_count_set( 0x00 );
        HAL_Delay(20);
        set_flash_setting_sector( Copy_APP3_To_APP1, rk.hyper_parameter.software_version );

        iap_btld.error_type = 0x05;
        upload_package = upload_iap_package;
        upload_package_init();
        upload_package_crc_end( upload_package() );
        uart_log("app1 can not start!\r\n");
        HAL_Delay(20);
        software_reset();
      }
      else
      {
        iap_btld.app1_start_count++;
        app1_start_count_set( iap_btld.app1_start_count );
      }

      HAL_Delay(50);
      uart_log("start app1...\r\n");
      HAL_Delay(50);
      if (!jump_app(APP_SECTOR_ADDR))
      {
        uart_log("start app1 failed: app1 no program\r\n");
        GPIO_MCU_WDI_Toggle;
        HAL_Delay(1000);
      }
      uart_log("no run app1...\r\n");
      break;

    case Recv_New_APP_To_APP2:
      if( !flag_first )
      {
        HAL_Delay(100);
        uart_log("start recv...\r\n");
        flag_first++;

        upload_package = upload_start_iap_update_package;
        upload_package_init();
        upload_package_crc_end( upload_package() );
      }

      if( (iap_btld.this_count == iap_btld.split_count) && iap_btld.split_count != 0 )
      {
        uart_log("recv complete!\r\n");
        process = Copy_APP2_To_APP1;
      }
      if( rk.timer.EC20_stop_work_timer >= 0.5f * A_Minute )
      {
        set_flash_setting_sector( Start_APP1, rk.hyper_parameter.software_version );
        uart_log("wait serverx iap update timeout!\r\n");

        iap_btld.error_type = 0x05;
        upload_package = upload_iap_package;
        upload_package_init();
        upload_package_crc_end( upload_package() );
        rk.flag.system_restart = true;
        return;
      }

      if( iap_btld.error_type != 0x00 )
      {
        set_flash_setting_sector( Start_APP1, rk.hyper_parameter.software_version );
        uart_log("revc server sub package error!\r\n");
        rk.flag.system_restart = true;
      }
      break;

    case Copy_APP2_To_APP1:

      if( rk.flag.iap_update_start == false )
      {
        break;
      }
      GPIO_MCU_WDI_Toggle;
      HAL_Delay(200);
      uart_log("start copy app2 to app1!\r\n");
       GPIO_MCU_WDI_Toggle;
      HAL_Delay(200);
      GPIO_MCU_WDI_Toggle;
      copy_flash_bin_128kb( ADDR_FLASH_SECTOR_6, APP_SECTOR_ADDR );
      uart_log("copy complete!\r\n");
      GPIO_MCU_WDI_Toggle;
      set_flash_setting_sector( Start_APP1, rk.hyper_parameter.software_version );
      software_reset();
      break;

    case Copy_APP3_To_APP1:
      if( !flag_first )
      {
        HAL_Delay(1000);
        GPIO_MCU_WDI_Toggle;
        flag_first++;
//        mcu_flash_read( SETTING_SECTOR_ADDR, iap_btld.flash_readdata, 3 );
//        process = iap_btld.flash_readdata[0];
//        if( process == Copy_APP3_To_APP1 )
//        {
//          upload_package_init();
//          upload_package_crc_end( upload_reset_app_bin_package() );
//          EC20_send_data( rk.upload.txbuf, rk.upload.txbuf[Package_Len_Pos]+Package_Aside_From_User_Data );
//        }

      }
      uart_log("start copy app3 to app1!\r\n");
      GPIO_MCU_WDI_Toggle;
      HAL_Delay(200);
      GPIO_MCU_WDI_Toggle;
      copy_flash_bin_128kb( ADDR_FLASH_SECTOR_7, APP_SECTOR_ADDR );
      uart_log("copy complete!\r\n");
      GPIO_MCU_WDI_Toggle;
      set_flash_setting_sector( Start_APP1, rk.hyper_parameter.software_version );
      HAL_Delay(200);
      software_reset();
      break;

    default:
      break;
  }
}

void bootloader( void )
{
  /* led闪烁 */
  led_work_flicker();

  /* 检查系统是否要重启 */
  check_system_status();

  /* 获取服务器的数据 */
  get_server_data();

  /* IAP升级 */
  bootloader_work();

  /* 上传数据至服务器 */
  upload_data_to_server();
}